  Algorithm Inventory: Homodyne → Heterodyne

  Legend

  - MS = Model-Specific (encodes homodyne physics assumptions; adaptation required)
  - MA = Model-Agnostic (works with any residual function; minimal/no adaptation)

  ---
  A. CORE PHYSICS (core/)

  A1. Rate Functions — physics_utils.py

  ┌───────────────────────────┬─────────────────────────────────────────────────────────┬─────────────────────────────────────────────────────┐
  │         Algorithm         │                    Homodyne Function                    │                  Model Assumptions                  │
  ├───────────────────────────┼─────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────┤
  │ Diffusion rate (MS)       │ calculate_diffusion_coefficient(t, D0, alpha, D_offset) │ Single-component D(t) = D₀·t^α + D_offset           │
  ├───────────────────────────┼─────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────┤
  │ Shear rate (MS)           │ calculate_shear_rate(t, γ̇₀, β, γ̇_offset)                │ Couette-cell shear: γ̇(t) = γ̇₀·t^β + γ̇_offset        │
  ├───────────────────────────┼─────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────┤
  │ Shear rate CMC (MS)       │ calculate_shear_rate_cmc(t, γ̇₀, β, γ̇_offset)            │ Same physics, extra dt/2 floor for element-wise t=0 │
  ├───────────────────────────┼─────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────┤
  │ Trapezoidal cumsum (MA)   │ trapezoid_cumsum(f)                                     │ Pure numerical integration; O(dt²)                  │
  ├───────────────────────────┼─────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────┤
  │ Time integral matrix (MA) │ create_time_integral_matrix(cumsum)                     │ Unsigned `                                          │
  ├───────────────────────────┼─────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────┤
  │ Safe sinc (MS)            │ safe_sinc(x)                                            │ Unnormalized sin(x)/x; Taylor expansion near 0      │
  ├───────────────────────────┼─────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────┤
  │ Safe exp (MA)             │ safe_exp(x, max_val=700)                                │ Generic overflow protection                         │
  └───────────────────────────┴─────────────────────────────────────────────────────────┴─────────────────────────────────────────────────────┘

  A2. Meshgrid Path — jax_backend.py

  ┌──────────────────────┬─────────────────────────────────────────────────────────────────────────────────────────┬─────────────────────────────────────────────────────────┐
  │      Algorithm       │                                    Homodyne Function                                    │                    Model Assumptions                    │
  ├──────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────┤
  │ g1 diffusion (MS)    │ _compute_g1_diffusion_meshgrid(params, t1, t2, ...)                                     │ g₁_diff = exp[-q²/2 · ∫D(t')dt']; single-component      │
  ├──────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────┤
  │ g1 shear (MS)        │ _compute_g1_shear_meshgrid(params, t1, t2, phi, ...)                                    │ g₁_shear = sinc²(qL/2π · cos(φ₀-φ) · ∫γ̇(t')dt')         │
  ├──────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────┤
  │ g1 total (MS)        │ _compute_g1_total_meshgrid(...)                                                         │ g₁ = g₁_diff × g₁_shear (multiplicative factorization)  │
  ├──────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────┤
  │ g2 scaled (MS)       │ compute_g2_scaled(params, t1, t2, phi, q, L, contrast, offset, dt)                      │ c₂ = offset + contrast × g₁²                            │
  ├──────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────┤
  │ g2 with factors (MS) │ compute_g2_scaled_with_factors(params, ..., wavevector_q²_half_dt, sinc_prefactor, ...) │ Pre-computed factors version; sinc_prefactor = qL·dt/2π │
  └──────────────────────┴─────────────────────────────────────────────────────────────────────────────────────────┴─────────────────────────────────────────────────────────┘

  A3. Element-Wise Path — physics_cmc.py

  ┌────────────────────────────────┬────────────────────────────────────────────────────────────────────────────┬──────────────────────────────────────────────────────────────────────┐
  │           Algorithm            │                             Homodyne Function                              │                          Model Assumptions                           │
  ├────────────────────────────────┼────────────────────────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────┤
  │ ShardGrid (MA)                 │ precompute_shard_grid(time_grid, t1, t2, dt)                               │ searchsorted index mapping; model-agnostic                           │
  ├────────────────────────────────┼────────────────────────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────┤
  │ g1 diffusion element-wise (MS) │ _compute_g1_diffusion_from_idx(params, idx1, idx2, time_safe, ...)         │ Same diffusion physics as meshgrid but via cumsum[idx2]-cumsum[idx1] │
  ├────────────────────────────────┼────────────────────────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────┤
  │ g1 shear element-wise (MS)     │ _compute_g1_shear_from_idx(params, idx1, idx2, time_safe, phi_unique, ...) │ sinc² shear at paired indices; vectorized over φ_unique              │
  ├────────────────────────────────┼────────────────────────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────┤
  │ g1 total with precomputed (MS) │ compute_g1_total_with_precomputed(params, phi_unique, shard_grid, ...)     │ g₁ = g₁_diff × g₁_shear; element-wise hot path                       │
  └────────────────────────────────┴────────────────────────────────────────────────────────────────────────────┴──────────────────────────────────────────────────────────────────────┘

  A4. Pre-computed Factors — physics_factors.py

  ┌──────────────────────┬──────────────────────────────────────┬────────────────────────────────────────────────────────────┐
  │      Algorithm       │          Homodyne Function           │                     Model Assumptions                      │
  ├──────────────────────┼──────────────────────────────────────┼────────────────────────────────────────────────────────────┤
  │ Physics factors (MS) │ PhysicsFactors.from_config(q, L, dt) │ Stores wavevector_q²_half_dt AND sinc_prefactor = qL·dt/2π │
  └──────────────────────┴──────────────────────────────────────┴────────────────────────────────────────────────────────────┘

  A5. Correlation Theory — theory.py

  ┌───────────────────┬───────────────────────────────────────┬────────────────────────────────────────────────────────┐
  │     Algorithm     │           Homodyne Function           │                   Model Assumptions                    │
  ├───────────────────┼───────────────────────────────────────┼────────────────────────────────────────────────────────┤
  │ TheoryEngine (MS) │ TheoryEngine(analysis_mode)           │ Wraps CombinedModel; dispatches static vs laminar_flow │
  ├───────────────────┼───────────────────────────────────────┼────────────────────────────────────────────────────────┤
  │ compute_g2 (MS)   │ TheoryEngine.compute_g2(params, ...)  │ 7-param → CombinedModel → g₁_diff × g₁_shear           │
  ├───────────────────┼───────────────────────────────────────┼────────────────────────────────────────────────────────┤
  │ chi-squared (MA)  │ TheoryEngine.compute_chi_squared(...) │ Generic sum-of-squares; model enters via compute_g2    │
  └───────────────────┴───────────────────────────────────────┴────────────────────────────────────────────────────────┘

  A6. Model Classes — models.py

  ┌──────────────────────┬────────────────────────────────────────────────────┬───────────────────────────────────────────────────────────────────────────────┐
  │      Algorithm       │                 Homodyne Function                  │                               Model Assumptions                               │
  ├──────────────────────┼────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
  │ DiffusionModel (MS)  │ DiffusionModel.compute_g1()                        │ 3 params: D0, α, D_offset                                                     │
  ├──────────────────────┼────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
  │ ShearModel (MS)      │ ShearModel.compute_g1()                            │ 4 params: γ̇₀, β, γ̇_offset, φ₀                                                 │
  ├──────────────────────┼────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
  │ CombinedModel (MS)   │ CombinedModel.compute_g1()                         │ 7 params; multiplicative g₁ = g₁_diff × g₁_shear; static or laminar_flow mode │
  ├──────────────────────┼────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
  │ Gradient mixin (MA)  │ GradientCapabilityMixin.get_gradient_function()    │ Generic JAX grad wrapper                                                      │
  ├──────────────────────┼────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
  │ Benchmark mixin (MA) │ BenchmarkingMixin.benchmark_gradient_performance() │ Generic timing                                                                │
  └──────────────────────┴────────────────────────────────────────────────────┴───────────────────────────────────────────────────────────────────────────────┘

  A7. Scaling Estimation — scaling_utils.py

  ┌───────────────────────────────┬────────────────────────────────────────────────────────────────┬─────────────────────────────────────────────────────────────────────────────────┐
  │           Algorithm           │                       Homodyne Function                        │                                Model Assumptions                                │
  ├───────────────────────────────┼────────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────┤
  │ Quantile contrast/offset (MS) │ estimate_contrast_offset_from_quantiles(c2_data, delta_t, ...) │ Assumes c₂ = offset + contrast × g₁² where g₁→0 at large lag, g₁≈1 at small lag │
  ├───────────────────────────────┼────────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────┤
  │ Per-angle scaling (MA)        │ estimate_per_angle_scaling(c2_data, t1, t2, phi_indices, ...)  │ Vectorized per-angle application of quantile estimator                          │
  ├───────────────────────────────┼────────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────┤
  │ Averaged scaling (MA)         │ compute_averaged_scaling(...)                                  │ Per-angle → mean                                                                │
  └───────────────────────────────┴────────────────────────────────────────────────────────────────┴─────────────────────────────────────────────────────────────────────────────────┘

  A8. Fitting Engine — fitting.py

  ┌────────────────────┬──────────────────────────────────────────────────┬──────────────────────────────────────────────────────────────────┐
  │     Algorithm      │                Homodyne Function                 │                        Model Assumptions                         │
  ├────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────┤
  │ 2×2 LS solver (MS) │ solve_least_squares_jax(theory_batch, exp_batch) │ Model: c₂_data = contrast × c₂_theory + offset; normal equations │
  ├────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────┤
  │ Gaussian NLL (MA)  │ UnifiedHomodyneEngine.compute_likelihood(...)    │ Generic Gaussian; model enters via compute_g2                    │
  └────────────────────┴──────────────────────────────────────────────────┴──────────────────────────────────────────────────────────────────┘

  A9. Diagonal Correction — diagonal_correction.py

  ┌─────────────────────────────┬─────────────────────────────────────────────────────────┬───────────────────────────────────────────────────────────┐
  │          Algorithm          │                    Homodyne Function                    │                     Model Assumptions                     │
  ├─────────────────────────────┼─────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────┤
  │ Basic correction (MA)       │ apply_diagonal_correction(c2_mat, method="basic")       │ Replace diagonal with side-band average; physics-agnostic │
  ├─────────────────────────────┼─────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────┤
  │ Statistical correction (MA) │ apply_diagonal_correction(c2_mat, method="statistical") │ Windowed estimator with trimmed mean; physics-agnostic    │
  ├─────────────────────────────┼─────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────┤
  │ Batch correction (MA)       │ apply_diagonal_correction_batch(c2_matrices, ...)       │ vmap over angles                                          │
  └─────────────────────────────┴─────────────────────────────────────────────────────────┴───────────────────────────────────────────────────────────┘

  A10. Numerical Gradients — numpy_gradients.py

  ┌──────────────────┬─────────────────────────────────────────────────────┬───────────────────────────────────────────────────────────────┐
  │    Algorithm     │                  Homodyne Function                  │                       Model Assumptions                       │
  ├──────────────────┼─────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────┤
  │ All methods (MA) │ numpy_gradient(func, ...), numpy_hessian(func, ...) │ Richardson, complex-step, adaptive; completely model-agnostic │
  └──────────────────┴─────────────────────────────────────────────────────┴───────────────────────────────────────────────────────────────┘

  ---
  B. NLSQ OPTIMIZATION (optimization/nlsq/)

  B1. Core Entry — core.py

  ┌─────────────────────────┬───────────────────────────────────────┬──────────────────────────────────────────────────────────────────────────────────────────┐
  │        Algorithm        │           Homodyne Function           │                                    Model Assumptions                                     │
  ├─────────────────────────┼───────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────┤
  │ fit_nlsq_jax (MS)       │ fit_nlsq_jax(data, config, ...)       │ Builds residual from compute_g2_scaled; 7-param indexing; phi extraction from data dict  │
  ├─────────────────────────┼───────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────┤
  │ fit_nlsq_multi_phi (MS) │ fit_nlsq_multi_phi(data, config, ...) │ Joint multi-angle fit; parameter vector = [physics₇ | fourier_contrast | fourier_offset] │
  ├─────────────────────────┼───────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────┤
  │ CMA-ES path (MS)        │ _fit_cmaes(...)                       │ CMA-ES objective wraps compute_g2_scaled residual; 7-param bounds                        │
  ├─────────────────────────┼───────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────┤
  │ Multi-start path (MA)   │ _fit_multistart(...)                  │ LHS sampling in bounds; model enters only via residual function                          │
  └─────────────────────────┴───────────────────────────────────────┴──────────────────────────────────────────────────────────────────────────────────────────┘

  B2. Adapters — adapter.py, adapter_base.py, wrapper.py

  ┌──────────────────────────┬───────────────────────────────────────────┬──────────────────────────────────────────────────────┐
  │        Algorithm         │             Homodyne Function             │                  Model Assumptions                   │
  ├──────────────────────────┼───────────────────────────────────────────┼──────────────────────────────────────────────────────┤
  │ NLSQAdapter.fit_jax (MA) │ NLSQAdapter.fit_jax(jax_residual_fn, ...) │ Generic; takes any residual function                 │
  ├──────────────────────────┼───────────────────────────────────────────┼──────────────────────────────────────────────────────┤
  │ NLSQWrapper.fit (MA)     │ NLSQWrapper.fit(residual_fn, ...)         │ scipy.optimize.least_squares wrapper; model-agnostic │
  ├──────────────────────────┼───────────────────────────────────────────┼──────────────────────────────────────────────────────┤
  │ Data preparation (MS)    │ NLSQAdapterBase._prepare_data(data)       │ Extracts phi, q, L, dt from homodyne data dict       │
  └──────────────────────────┴───────────────────────────────────────────┴──────────────────────────────────────────────────────┘

  B3. Residual Functions — strategies/residual.py, residual_jit.py

  ┌──────────────────────────┬────────────────────────────────────────────────┬─────────────────────────────────────────────────────────────────────────────────┐
  │        Algorithm         │               Homodyne Function                │                                Model Assumptions                                │
  ├──────────────────────────┼────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────┤
  │ Stratified residual (MS) │ StratifiedResidualFunction.__call__(params)    │ Parameter layout: [contrast₀..ₙ, offset₀..ₙ, physics₇]; calls compute_g2_scaled │
  ├──────────────────────────┼────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────┤
  │ JIT residual (MS)        │ StratifiedResidualFunctionJIT.__call__(params) │ Same as above, JIT-compiled                                                     │
  └──────────────────────────┴────────────────────────────────────────────────┴─────────────────────────────────────────────────────────────────────────────────┘

  B4. Fourier Reparameterization — fourier_reparam.py

  ┌─────────────────────────────┬────────────────────────────────────────────────┬─────────────────────────────────────────────────────────────────────┐
  │          Algorithm          │               Homodyne Function                │                          Model Assumptions                          │
  ├─────────────────────────────┼────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────┤
  │ FourierReparameterizer (MA) │ fourier_to_per_angle(), per_angle_to_fourier() │ Generic Fourier basis; no model assumptions on contrast/offset form │
  ├─────────────────────────────┼────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────┤
  │ Config (MA)                 │ FourierReparamConfig                           │ Bounds for c₀, cₖ, o₀, oₖ coefficients                              │
  └─────────────────────────────┴────────────────────────────────────────────────┴─────────────────────────────────────────────────────────────────────┘

  B5. Anti-Degeneracy — anti_degeneracy_controller.py

  ┌───────────────────────────────┬─────────────────────────────────────┬───────────────────────────────────────────────────────────────────────┐
  │           Algorithm           │          Homodyne Function          │                           Model Assumptions                           │
  ├───────────────────────────────┼─────────────────────────────────────┼───────────────────────────────────────────────────────────────────────┤
  │ 5-layer controller (MS)       │ AntiDegeneracyController.apply(...) │ Layer 5 is shear_weighting (sinc-specific); layers 1-4 model-agnostic │
  ├───────────────────────────────┼─────────────────────────────────────┼───────────────────────────────────────────────────────────────────────┤
  │ Per-angle mode selection (MA) │ AntiDegeneracyConfig.per_angle_mode │ Generic mode routing                                                  │
  └───────────────────────────────┴─────────────────────────────────────┴───────────────────────────────────────────────────────────────────────┘

  B6. Shear Weighting — shear_weighting.py

  ┌────────────────────────────────┬─────────────────────────────────────────────────────┬──────────────────────────────────────────────────────────┐
  │           Algorithm            │                  Homodyne Function                  │                    Model Assumptions                     │
  ├────────────────────────────────┼─────────────────────────────────────────────────────┼──────────────────────────────────────────────────────────┤
  │ Shear sensitivity weights (MS) │ compute_shear_weights(phi_angles, gamma_dot_params) │ Weights ∝ sinc sensitivity; sinc² model is homodyne-only │
  └────────────────────────────────┴─────────────────────────────────────────────────────┴──────────────────────────────────────────────────────────┘

  B7. Hierarchical Optimization — hierarchical.py

  ┌────────────────────┬─────────────────────────────────────┬─────────────────────────────────────────────────────────────────────────────────┐
  │     Algorithm      │          Homodyne Function          │                                Model Assumptions                                │
  ├────────────────────┼─────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────┤
  │ Two-stage fit (MS) │ fit_hierarchical(data, config, ...) │ Stage 1: fix scaling, fit physics₇; Stage 2: fix physics, fit per-angle scaling │
  └────────────────────┴─────────────────────────────────────┴─────────────────────────────────────────────────────────────────────────────────┘

  B8. Jacobian — jacobian.py

  ┌────────────────────────┬─────────────────────┬─────────────────────────────────────────────────────────┐
  │       Algorithm        │  Homodyne Function  │                    Model Assumptions                    │
  ├────────────────────────┼─────────────────────┼─────────────────────────────────────────────────────────┤
  │ Jacobian analysis (MA) │ analyze_jacobian(J) │ Condition number, rank, singular values; model-agnostic │
  └────────────────────────┴─────────────────────┴─────────────────────────────────────────────────────────┘

  B9. Other NLSQ files (all MA)

  ┌────────────────────────────────┬───────────────────────────────────────────┐
  │              File              │              Key Algorithms               │
  ├────────────────────────────────┼───────────────────────────────────────────┤
  │ fallback_chain.py              │ Strategy selection, automatic degradation │
  ├────────────────────────────────┼───────────────────────────────────────────┤
  │ recovery.py                    │ 3-attempt retry with perturbation         │
  ├────────────────────────────────┼───────────────────────────────────────────┤
  │ cmaes_wrapper.py               │ CMA-ES via evosax (takes any objective)   │
  ├────────────────────────────────┼───────────────────────────────────────────┤
  │ multistart.py                  │ LHS + parallel execution                  │
  ├────────────────────────────────┼───────────────────────────────────────────┤
  │ adaptive_regularization.py     │ CV-based λ selection                      │
  ├────────────────────────────────┼───────────────────────────────────────────┤
  │ gradient_monitor.py            │ Gradient norm tracking                    │
  ├────────────────────────────────┼───────────────────────────────────────────┤
  │ transforms.py                  │ Parameter scaling/centering               │
  ├────────────────────────────────┼───────────────────────────────────────────┤
  │ strategies/stratified_ls.py    │ Angle-stratified chunking                 │
  ├────────────────────────────────┼───────────────────────────────────────────┤
  │ strategies/hybrid_streaming.py │ Streaming gradient accumulation           │
  ├────────────────────────────────┼───────────────────────────────────────────┤
  │ strategies/out_of_core.py      │ Disk-based JTJ accumulation               │
  ├────────────────────────────────┼───────────────────────────────────────────┤
  │ strategies/sequential.py       │ Per-angle sequential fit                  │
  ├────────────────────────────────┼───────────────────────────────────────────┤
  │ validation/                    │ Input, fit quality, convergence checks    │
  └────────────────────────────────┴───────────────────────────────────────────┘

  ---
  C. CMC OPTIMIZATION (optimization/cmc/)

  C1. Core — core.py

  ┌────────────────────────┬──────────────────────────────────────────────────┬────────────────────────────────────────────────────────────────┐
  │       Algorithm        │                Homodyne Function                 │                       Model Assumptions                        │
  ├────────────────────────┼──────────────────────────────────────────────────┼────────────────────────────────────────────────────────────────┤
  │ fit_mcmc_jax (MS)      │ fit_mcmc_jax(data, config, parameter_space, ...) │ Builds NumPyro model from homodyne parameter space; 7+2 params │
  ├────────────────────────┼──────────────────────────────────────────────────┼────────────────────────────────────────────────────────────────┤
  │ Shard combination (MA) │ Consensus MC (Scott et al. 2016)                 │ Precision-weighted means; model-agnostic                       │
  └────────────────────────┴──────────────────────────────────────────────────┴────────────────────────────────────────────────────────────────┘

  C2. NumPyro Model — model.py

  ┌──────────────────────┬────────────────────────────────────────────────┬──────────────────────────────────────────────────────────────────────────────┐
  │      Algorithm       │               Homodyne Function                │                              Model Assumptions                               │
  ├──────────────────────┼────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────┤
  │ xpcs_model (MS)      │ get_xpcs_model(per_angle_mode, reparam_config) │ Samples 7 physics + 2×n_phi scaling; calls compute_g1_total_with_precomputed │
  ├──────────────────────┼────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────┤
  │ Per-angle modes (MA) │ individual/auto/constant/constant_averaged     │ Generic scaling mode dispatch                                                │
  └──────────────────────┴────────────────────────────────────────────────┴──────────────────────────────────────────────────────────────────────────────┘

  C3. Priors — priors.py

  ┌───────────────────────────┬──────────────────────────────────────────────────┬──────────────────────────────────────────────────────┐
  │         Algorithm         │                Homodyne Function                 │                  Model Assumptions                   │
  ├───────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────────┤
  │ Default priors (MS)       │ build_default_priors(param_space, ...)           │ Prior μ/σ from homodyne registry (D₀, α, γ̇₀, β, ...) │
  ├───────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────────┤
  │ NLSQ-informed priors (MS) │ build_nlsq_informed_priors(nlsq_result, ...)     │ Centers on 7-param NLSQ MAP                          │
  ├───────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────────┤
  │ Data-driven scaling (MS)  │ estimate_contrast_offset_from_data(c2_data, ...) │ Quantile estimation (same as scaling_utils)          │
  └───────────────────────────┴──────────────────────────────────────────────────┴──────────────────────────────────────────────────────┘

  C4. Reparameterization — reparameterization.py

  ┌─────────────────────────┬──────────────────────────────────────┬────────────────────────────────────────┐
  │        Algorithm        │          Homodyne Function           │           Model Assumptions            │
  ├─────────────────────────┼──────────────────────────────────────┼────────────────────────────────────────┤
  │ t_ref computation (MA)  │ compute_t_ref(dt, t_max)             │ Geometric mean; model-agnostic         │
  ├─────────────────────────┼──────────────────────────────────────┼────────────────────────────────────────┤
  │ D₀↔α decorrelation (MS) │ transform_nlsq_to_reparam_space(...) │ D_ref = D₀ × t_ref^α; single-component │
  ├─────────────────────────┼──────────────────────────────────────┼────────────────────────────────────────┤
  │ γ̇₀↔β decorrelation (MS) │ Same function                        │ log_gamma_ref = log(γ̇₀ × t_ref^β)      │
  └─────────────────────────┴──────────────────────────────────────┴────────────────────────────────────────┘

  C5. Scaling — scaling.py

  ┌───────────────────────┬───────────────────────────────────────────┬────────────────────────────────┐
  │       Algorithm       │             Homodyne Function             │       Model Assumptions        │
  ├───────────────────────┼───────────────────────────────────────────┼────────────────────────────────┤
  │ ParameterScaling (MA) │ sample_scaled_parameter(), smooth_bound() │ Generic tanh-bounded transform │
  └───────────────────────┴───────────────────────────────────────────┴────────────────────────────────┘

  C6. Diagnostics — diagnostics.py

  ┌──────────────────────┬─────────────────────────────────────┬──────────────────────────┐
  │      Algorithm       │          Homodyne Function          │    Model Assumptions     │
  ├──────────────────────┼─────────────────────────────────────┼──────────────────────────┤
  │ All diagnostics (MA) │ R-hat, ESS, BFMI, bimodal detection │ Generic MCMC diagnostics │
  └──────────────────────┴─────────────────────────────────────┴──────────────────────────┘

  C7. Backends — backends/

  ┌───────────────────┬──────────────────────────────────────────────────────────┐
  │     Algorithm     │                    Model Assumptions                     │
  ├───────────────────┼──────────────────────────────────────────────────────────┤
  │ All backends (MA) │ Process management; model enters only via model function │
  └───────────────────┴──────────────────────────────────────────────────────────┘

  ---
  D. CONFIG & DATA

  D1. Parameter Registry — config/parameter_registry.py

  ┌───────────────────────┬─────────────────────────────────────────────────────────────────────┐
  │       Algorithm       │                          Model Assumptions                          │
  ├───────────────────────┼─────────────────────────────────────────────────────────────────────┤
  │ Registry entries (MS) │ 7 physics params (D₀, α, D_offset, γ̇₀, β, γ̇_offset, φ₀) + 2 scaling │
  ├───────────────────────┼─────────────────────────────────────────────────────────────────────┤
  │ Analysis modes (MS)   │ "static" (3 params), "laminar_flow" (7 params)                      │
  └───────────────────────┴─────────────────────────────────────────────────────────────────────┘

  D2. Parameter Space — config/parameter_space.py

  ┌─────────────────────────────────┬─────────────────────────────────────────────────────────┐
  │            Algorithm            │                    Model Assumptions                    │
  ├─────────────────────────────────┼─────────────────────────────────────────────────────────┤
  │ Prior specs (MS)                │ TruncatedNormal/LogNormal/BetaScaled per homodyne param │
  ├─────────────────────────────────┼─────────────────────────────────────────────────────────┤
  │ Single-angle stabilization (MA) │ Tightens contrast/offset; generic                       │
  └─────────────────────────────────┴─────────────────────────────────────────────────────────┘

  D3. Physics Validators — config/physics_validators.py

  ┌───────────────────────┬───────────────────┐
  │       Algorithm       │ Model Assumptions │
  ├───────────────────────┼───────────────────┤
  │ Constraint rules (MS) │ D₀>0, γ̇₀≥0,       │
  └───────────────────────┴───────────────────┘

  ---
  Adaptation Plan: Homodyne → Heterodyne

  Fundamental Model Delta

  ┌──────────────────┬────────────────────────────────────┬───────────────────────────────────────────────────────────────────────────────────────────┬─────────────────────────────────────┐
  │      Aspect      │              Homodyne              │                                        Heterodyne                                         │               Impact                │
  ├──────────────────┼────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────────────────┼─────────────────────────────────────┤
  │ Component count  │ 1 (single scattering)              │ 2 (reference + sample)                                                                    │ Doubles transport computation       │
  ├──────────────────┼────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────────────────┼─────────────────────────────────────┤
  │ Correlation form │ c₂ = offset + contrast × g₁²       │ c₂ = offset + contrast × (ref + sample + cross)/f²                                        │ Additive 3-term, not multiplicative │
  ├──────────────────┼────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────────────────┼─────────────────────────────────────┤
  │ Shear/velocity   │ sinc²(qL/2π · cos(φ)·∫γ̇ dt)        │ cos(q·cos(φ)·∫v dt)                                                                       │ Phase factor, not sinc envelope     │
  ├──────────────────┼────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────────────────┼─────────────────────────────────────┤
  │ Fraction         │ None (implicit f=1)                │ f_s(t) = f₀·exp(f₁·(t-f₂)) + f₃                                                           │ 4 extra fraction params             │
  ├──────────────────┼────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────────────────┼─────────────────────────────────────┤
  │ Physics params   │ 7 (D₀, α, D_off, γ̇₀, β, γ̇_off, φ₀) │ 14 (D₀_ref, α_ref, D_off_ref, D₀_sam, α_sam, D_off_sam, v₀, β, v_off, f₀, f₁, f₂, f₃, φ₀) │ 2× parameter count                  │
  ├──────────────────┼────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────────────────┼─────────────────────────────────────┤
  │ Normalization    │ None (g₁² ∈ [0,1] naturally)       │ f² = (f_s²+f_r²)₁·(f_s²+f_r²)₂                                                            │ Explicit fraction normalization     │
  ├──────────────────┼────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────────────────┼─────────────────────────────────────┤
  │ sinc_prefactor   │ qL·dt/2π (used in shear)           │ Not used (velocity enters cosine directly)                                                │ Factor removed                      │
  └──────────────────┴────────────────────────────────────┴───────────────────────────────────────────────────────────────────────────────────────────┴─────────────────────────────────────┘

  ---
  Status Key

  - DONE = Already correctly adapted in heterodyne (confirmed by agent analysis)
  - REMOVED = Not applicable to heterodyne; correctly absent
  - ADAPT = Exists but may need verification/update
  - MISSING = Not present in heterodyne; needs porting decision

  ---
  A. CORE PHYSICS ADAPTATIONS

  A1. physics_utils.py — Rate Functions

  Status: DONE

  ┌─────────────────────────────────────────────┬────────────────────────────────────────┬─────────────────────┬────────────────────────────────────────────────────────────────────────────────────────────┐
  │                  Homodyne                   │               Heterodyne               │        Delta        │                                       Justification                                        │
  ├─────────────────────────────────────────────┼────────────────────────────────────────┼─────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────┤
  │ calculate_diffusion_coefficient(t, D0,      │ compute_transport_rate(t, D0, alpha,   │ Renamed;            │ Heterodyne has TWO transport components (ref + sample), each calling this with different   │
  │ alpha, D_offset)                            │ offset)                                │ semantically        │ params. Name "transport" is more general than "diffusion" since it covers both reference   │
  │                                             │                                        │ identical           │ beam and sample beam decay.                                                                │
  ├─────────────────────────────────────────────┼────────────────────────────────────────┼─────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────┤
  │ calculate_shear_rate(t, γ̇₀, β, γ̇_offset)    │ compute_velocity_rate(t, v0, beta,     │ Renamed; not        │ Homodyne floors γ̇≥0 because shear enters sinc²(∫γ̇) where negative shear is unphysical.     │
  │                                             │ v_offset)                              │ floored at 0        │ Heterodyne velocity enters cos(∫v) where negative velocity is meaningful (reversed flow).  │
  ├─────────────────────────────────────────────┼────────────────────────────────────────┼─────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────┤
  │ safe_sinc(x)                                │ safe_sinc(x)                           │ Retained            │ Used in heterodyne for potential future extensions; not in main correlation path.          │
  ├─────────────────────────────────────────────┼────────────────────────────────────────┼─────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────┤
  │ trapezoid_cumsum(f)                         │ trapezoid_cumsum(f, dt)                │ dt parameter added  │ Homodyne multiplies dt outside; heterodyne includes dt in the cumsum to avoid repeated     │
  │                                             │                                        │                     │ multiplication at call sites.                                                              │
  ├─────────────────────────────────────────────┼────────────────────────────────────────┼─────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────┤
  │ create_time_integral_matrix(cumsum)         │ create_time_integral_matrix(cumsum)    │ Identical           │ Model-agnostic signed difference matrix; smooth_abs applied by caller when needed.         │
  └─────────────────────────────────────────────┴────────────────────────────────────────┴─────────────────────┴────────────────────────────────────────────────────────────────────────────────────────────┘

  A2. jax_backend.py — Meshgrid Correlation

  Status: DONE (completely rewritten)

  ┌───────────────────────────────────────────┬──────────────────────────────────────────────┬──────────────────┬───────────────────────────────────────────────────────────────────────────────────────────┐
  │                 Homodyne                  │                  Heterodyne                  │      Delta       │                                       Justification                                       │
  ├───────────────────────────────────────────┼──────────────────────────────────────────────┼──────────────────┼───────────────────────────────────────────────────────────────────────────────────────────┤
  │ compute_g2_scaled(params₇, t1, t2, phi,   │ compute_c2_heterodyne(params₁₄, t, q, dt,    │                  │ Homodyne: single g₁ = g₁_diff×g₁_shear, then c₂ = offset+contrast×g₁². Heterodyne: three  │
  │ q, L, ...)                                │ phi_angle, ...)                              │ Complete rewrite │ additive terms (ref, sample, cross) with fraction weighting and normalization. No code    │
  │                                           │                                              │                  │ can be shared.                                                                            │
  ├───────────────────────────────────────────┼──────────────────────────────────────────────┼──────────────────┼───────────────────────────────────────────────────────────────────────────────────────────┤
  │ _compute_g1_diffusion_meshgrid(...)       │ Inlined into compute_c2_heterodyne as        │ Split into two   │ Heterodyne computes exp(-q²/2·∫J_ref dt) and exp(-q²/2·∫J_sample dt) separately, then     │
  │                                           │ half_tr_ref, half_tr_sample                  │ components       │ combines in 3-term formula.                                                               │
  ├───────────────────────────────────────────┼──────────────────────────────────────────────┼──────────────────┼───────────────────────────────────────────────────────────────────────────────────────────┤
  │ _compute_g1_shear_meshgrid(...)           │ Replaced by velocity phase: cos(q·cos(φ)·∫v  │ sinc² → cos      │ Homodyne shear sinc models Couette-cell angular decorrelation. Heterodyne velocity cos    │
  │                                           │ dt)                                          │                  │ models directed flow phase in cross-term only. Fundamentally different physics.           │
  ├───────────────────────────────────────────┼──────────────────────────────────────────────┼──────────────────┼───────────────────────────────────────────────────────────────────────────────────────────┤
  │ Pre-computed sinc_prefactor = qL·dt/2π    │ Not used                                     │ Removed          │ sinc_prefactor encoded stator-rotor gap L; heterodyne velocity phase uses q·cos(φ)        │
  │                                           │                                              │                  │ directly without L.                                                                       │
  ├───────────────────────────────────────────┼──────────────────────────────────────────────┼──────────────────┼───────────────────────────────────────────────────────────────────────────────────────────┤
  │ wavevector_q_squared_half_dt              │ Retained                                     │ Same             │ q²/2·dt enters transport decay identically in both models.                                │
  └───────────────────────────────────────────┴──────────────────────────────────────────────┴──────────────────┴───────────────────────────────────────────────────────────────────────────────────────────┘

  A3. physics_cmc.py — Element-Wise Path

  Status: DONE (completely rewritten)

  ┌───────────────────────────────────────────────────────┬─────────────────────────────────────────────────────┬────────────────────┬──────────────────────────────────────────────────────────────────────┐
  │                       Homodyne                        │                     Heterodyne                      │       Delta        │                            Justification                             │
  ├───────────────────────────────────────────────────────┼─────────────────────────────────────────────────────┼────────────────────┼──────────────────────────────────────────────────────────────────────┤
  │ compute_g1_total_with_precomputed(params₇,            │ compute_c2_elementwise(params₁₄, shard_grid, q, dt, │ Returns c₂         │ Heterodyne can't factorize g₁ = g₁_diff × g₁_shear because           │
  │ phi_unique, shard_grid, ...)                          │  phi_angle, ...)                                    │ directly, not g₁   │ correlation is additive 3-term, not multiplicative. Must compute     │
  │                                                       │                                                     │                    │ full c₂ in one function.                                             │
  ├───────────────────────────────────────────────────────┼─────────────────────────────────────────────────────┼────────────────────┼──────────────────────────────────────────────────────────────────────┤
  │                                                       │                                                     │ Slightly different │ Heterodyne stores time_grid (full array) + n_pairs count instead of  │
  │ ShardGrid(time_safe, idx1, idx2, dt_safe)             │ ShardGrid(time_grid, idx1, idx2, n_pairs)           │  fields            │ time_safe + dt_safe. Both serve same purpose: pre-computed indices   │
  │                                                       │                                                     │                    │ for cumsum lookup.                                                   │
  ├───────────────────────────────────────────────────────┼─────────────────────────────────────────────────────┼────────────────────┼──────────────────────────────────────────────────────────────────────┤
  │ _compute_g1_diffusion_from_idx(...)                   │ compute_transport_elementwise(shard_grid, D0,       │ Returns half_tr,   │ Heterodyne needs half_tr = exp(-q²/2·∫J dt) separately for ref and   │
  │                                                       │ alpha, offset, q, dt)                               │ not g₁             │ sample, then combines in 3-term formula.                             │
  ├───────────────────────────────────────────────────────┼─────────────────────────────────────────────────────┼────────────────────┼──────────────────────────────────────────────────────────────────────┤
  │                                                       │ compute_velocity_elementwise(shard_grid, v0, beta,  │ Returns signed     │ Heterodyne returns ∫v dt (signed) for cos(phase) computation.        │
  │ _compute_g1_shear_from_idx(...)                       │ v_offset, dt)                                       │ integral, not      │ Homodyne returned sinc² of ∫γ̇ dt.                                    │
  │                                                       │                                                     │ sinc²              │                                                                      │
  └───────────────────────────────────────────────────────┴─────────────────────────────────────────────────────┴────────────────────┴──────────────────────────────────────────────────────────────────────┘

  A4. physics_factors.py — Pre-computed Constants

  Status: DONE (simplified)

  ┌────────────────────────────────────────────────────┬───────────────────────────────────────┬─────────────────────────────┬───────────────────────────────────────────────────────────────────────────────┐
  │                      Homodyne                      │              Heterodyne               │            Delta            │                                 Justification                                 │
  ├────────────────────────────────────────────────────┼───────────────────────────────────────┼─────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
  │ PhysicsFactors(q, L, dt, wavevector_q²_half_dt,    │ PhysicsFactors(q, dt,                 │ sinc_prefactor removed; L   │ Heterodyne has no sinc term and no stator-rotor gap L. Velocity phase uses    │
  │ sinc_prefactor)                                    │ wavevector_q²_half_dt)                │ removed                     │ q·cos(φ) computed at call time.                                               │
  └────────────────────────────────────────────────────┴───────────────────────────────────────┴─────────────────────────────┴───────────────────────────────────────────────────────────────────────────────┘

  A5. theory.py — Theory Engine

  Status: DONE (rewritten)

  ┌──────────────────────────────────────────────────────┬──────────────────────────────────────────────┬─────────────────────────────────┬─────────────────────────────────────────────────────────────────┐
  │                       Homodyne                       │                  Heterodyne                  │              Delta              │                          Justification                          │
  ├──────────────────────────────────────────────────────┼──────────────────────────────────────────────┼─────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
  │ TheoryEngine(analysis_mode="laminar_flow") →         │ TheoryEngine(t, q, dt, n_params=14)          │ Stateless → stateful with       │ Heterodyne engine stores experimental setup; no analysis_mode   │
  │ CombinedModel                                        │                                              │ stored t, q, dt                 │ dispatch (always 14-param).                                     │
  ├──────────────────────────────────────────────────────┼──────────────────────────────────────────────┼─────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
  │ compute_g2() → CombinedModel.compute_g1() → g₁²      │ compute_correlation() →                      │ Direct c₂, no intermediate g₁   │ Heterodyne c₂ is not expressible as contrast×g₁²; must compute  │
  │                                                      │ compute_c2_heterodyne()                      │                                 │ 3-term sum directly.                                            │
  ├──────────────────────────────────────────────────────┼──────────────────────────────────────────────┼─────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
  │ compute_g2_theory(params₇, ..., analysis_mode)       │ compute_c2_theory(params₁₄, t, q, dt,        │ 14 params; no mode dispatch     │ Heterodyne always uses full model.                              │
  │                                                      │ phi_angle, ...)                              │                                 │                                                                 │
  └──────────────────────────────────────────────────────┴──────────────────────────────────────────────┴─────────────────────────────────┴─────────────────────────────────────────────────────────────────┘

  A6. models.py — Model Classes

  Status: DONE (rewritten)

  ┌───────────────────────────────────────┬───────────────────────────────────────────────┬────────────────────────┬────────────────────────────────────────────────────────────────────────────────────────┐
  │               Homodyne                │                  Heterodyne                   │         Delta          │                                     Justification                                      │
  ├───────────────────────────────────────┼───────────────────────────────────────────────┼────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────┤
  │ CombinedModel(analysis_mode) — 7      │ TwoComponentModel — 14 params                 │ Completely different   │ Homodyne: multiplicative g₁ = g₁_diff × g₁_shear. Heterodyne: additive                 │
  │ params                                │                                               │ class                  │ (ref+sample+cross)/f².                                                                 │
  ├───────────────────────────────────────┼───────────────────────────────────────────────┼────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────┤
  │ DiffusionModel — 3 params             │ ReducedModel(active_params)                   │ Generic reduced model  │ Heterodyne uses general ReducedModel that can freeze any subset; not physics-specific  │
  │                                       │                                               │                        │ subclasses.                                                                            │
  ├───────────────────────────────────────┼───────────────────────────────────────────────┼────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────┤
  │ ShearModel — 4 params                 │ No equivalent                                 │ Removed                │ Shear-only model makes no physical sense in heterodyne geometry.                       │
  ├───────────────────────────────────────┼───────────────────────────────────────────────┼────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────┤
  │ Analysis modes: "static",             │ Modes: "static_ref", "static_both",           │ Different mode         │ Homodyne: static=no shear. Heterodyne: static_ref=only reference transport;            │
  │ "laminar_flow"                        │ "two_component"                               │ semantics              │ two_component=full 14-param.                                                           │
  └───────────────────────────────────────┴───────────────────────────────────────────────┴────────────────────────┴────────────────────────────────────────────────────────────────────────────────────────┘

  A7. scaling_utils.py — Quantile Estimation

  Status: DONE (adapted)

  ┌──────────────────────────────────────────────────────────┬──────────────────────┬────────────────┬──────────────────────────────────────────────────────────────────────────────────────────────────────┐
  │                         Homodyne                         │      Heterodyne      │     Delta      │                                            Justification                                             │
  ├──────────────────────────────────────────────────────────┼──────────────────────┼────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────┤
  │ estimate_contrast_offset_from_quantiles(c2_data,         │ Same function        │ Identical      │ Both models have c₂ → offset at large lag and c₂ → offset+contrast at small lag. The physics basis   │
  │ delta_t, ...)                                            │ signature            │ algorithm      │ is identical even though the correlation structure differs.                                          │
  ├──────────────────────────────────────────────────────────┼──────────────────────┼────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────┤
  │ Contrast bounds: (0.0, 1.0)                              │ Contrast bounds:     │ Wider bounds   │ Homodyne g₁² ∈ [0,1] so contrast ∈ [0,1]. Heterodyne (ref+sample+cross)/f² can exceed 1 depending on │
  │                                                          │ (0.0, 10.0)          │                │  fraction balance, so contrast bounds are wider.                                                     │
  ├──────────────────────────────────────────────────────────┼──────────────────────┼────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────┤
  │ Offset bounds: (0.5, 1.5)                                │ Offset bounds:       │ Different      │ Heterodyne offset can be negative due to interference cross-term; homodyne offset is always ≥1       │
  │                                                          │ (-1.0, 1.0)          │ range          │ (Siegert relation baseline).                                                                         │
  └──────────────────────────────────────────────────────────┴──────────────────────┴────────────────┴──────────────────────────────────────────────────────────────────────────────────────────────────────┘

  A8. fitting.py — LS Solver & Engine

  Status: DONE (adapted)

  ┌──────────────────────────────────────┬─────────────────────────────────────┬─────────────────────────────────┬───────────────────────────────────────────────────────────────────────────────────────────┐
  │               Homodyne               │             Heterodyne              │              Delta              │                                       Justification                                       │
  ├──────────────────────────────────────┼─────────────────────────────────────┼─────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────────────────┤
  │ solve_least_squares_jax(theory, exp) │ Same                                │ Identical algorithm             │ The 2×2 normal equation solver is model-agnostic; it fits contrast and offset given any   │
  │                                      │                                     │                                 │ theory/data pair.                                                                         │
  ├──────────────────────────────────────┼─────────────────────────────────────┼─────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────────────────┤
  │ ParameterSpace — homodyne            │ ParameterSpace — heterodyne         │ Different parameter set         │ Heterodyne ParameterSpace references 14-param registry with different bounds (D₀ up to    │
  │ bounds/priors                        │ bounds/priors                       │                                 │ 1e6, velocity params, fraction params).                                                   │
  ├──────────────────────────────────────┼─────────────────────────────────────┼─────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────────────────┤
  │ UnifiedHomodyneEngine                │ UnifiedHeterodyneEngine             │ Renamed; calls                  │ Same structure but dispatches to heterodyne correlation computation.                      │
  │                                      │                                     │ compute_c2_heterodyne           │                                                                                           │
  └──────────────────────────────────────┴─────────────────────────────────────┴─────────────────────────────────┴───────────────────────────────────────────────────────────────────────────────────────────┘

  A9. diagonal_correction.py

  Status: DONE (unchanged)
  Model-agnostic. Operates on raw c₂ matrix regardless of physics model. No adaptation needed.

  A10. numpy_gradients.py

  Status: DONE (unchanged)
  Completely model-agnostic numerical differentiation. No adaptation needed.

  A11. model_mixins.py

  Status: DONE (simplified; 20k → 7.2k)
  Retained gradient capability mixin; removed homodyne-specific benchmark and optimization recommendation methods that referenced 7-param model.

  ---
  B. NLSQ OPTIMIZATION ADAPTATIONS

  B1. nlsq/core.py — Main Entry

  Status: DONE (2550 → 913 lines)

  ┌─────────────────────────────────────────────┬──────────────────────────────────────────────────┬──────────────┬────────────────────────────────────────────────────────────────────────────────────────┐
  │                  Homodyne                   │                    Heterodyne                    │    Delta     │                                     Justification                                      │
  ├─────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────────┼────────────────────────────────────────────────────────────────────────────────────────┤
  │ fit_nlsq_jax(data, config, ...) takes data  │ fit_nlsq_jax(model, c2_data, phi_angle, config,  │ Interface    │ Heterodyne passes stateful HeterodyneModel (stores t, q, dt, params) rather than a     │
  │ dict with homodyne keys                     │ ...) takes HeterodyneModel                       │ change       │ data dict. Residual function built from model.create_residual_function().              │
  ├─────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────────┼────────────────────────────────────────────────────────────────────────────────────────┤
  │ Parameter vector: [contrast₀..ₙ,            │ [physics₁₄] (scaling separate in                 │ Scaling      │ Heterodyne separates physics params (14-vector) from per-angle scaling (managed by     │
  │ offset₀..ₙ, D₀, α, D_off, γ̇₀, β, γ̇_off, φ₀] │ PerAngleScaling)                                 │ decoupled    │ PerAngleScaling dataclass). Homodyne concatenated them.                                │
  ├─────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────────┼────────────────────────────────────────────────────────────────────────────────────────┤
  │ _fit_cmaes() uses 7-param bounds            │ Uses 14-param bounds from                        │ Wider search │ CMA-ES population size and sigma₀ may need tuning for 14D vs 7D.                       │
  │                                             │ HeterodyneModel.param_manager                    │  space       │                                                                                        │
  └─────────────────────────────────────────────┴──────────────────────────────────────────────────┴──────────────┴────────────────────────────────────────────────────────────────────────────────────────┘

  B2. nlsq/adapter.py

  Status: DONE (adapted)

  ┌────────────────────────────────┬───────────────────────────────────────────┬────────────────────────────┬──────────────────────────────────────────────────────────────────────────────────────────────┐
  │            Homodyne            │                Heterodyne                 │           Delta            │                                        Justification                                         │
  ├────────────────────────────────┼───────────────────────────────────────────┼────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────┤
  │ Cache key includes             │ Cache key includes phi_angles +           │ Different cache            │ Heterodyne doesn't have analysis_mode (always 14-param); cache keys must capture per-angle   │
  │ analysis_mode                  │ scaling_mode                              │ invalidation               │ config.                                                                                      │
  └────────────────────────────────┴───────────────────────────────────────────┴────────────────────────────┴──────────────────────────────────────────────────────────────────────────────────────────────┘

  B3. nlsq/fourier_reparam.py

  Status: DONE (minimal changes)
  Model-agnostic Fourier basis for contrast(φ) and offset(φ). Coefficient bounds adjusted for heterodyne's wider contrast range.

  B4. nlsq/anti_degeneracy_controller.py

  Status: DONE (1021 → 450 lines)

  ┌───────────────────────────────────┬───────────────┬─────────────────────────────┬────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
  │             Homodyne              │  Heterodyne   │            Delta            │                                                     Justification                                                      │
  ├───────────────────────────────────┼───────────────┼─────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
  │ 5-layer defense (including        │ 4-layer       │ Layer 5 (shear_weighting)   │ Shear-sensitivity weighting is sinc²-specific. Heterodyne velocity phase cos(q·cos(φ)·∫v dt) has different angular     │
  │ shear_weighting)                  │ defense       │ removed                     │ sensitivity that doesn't benefit from sinc-based weighting.                                                            │
  └───────────────────────────────────┴───────────────┴─────────────────────────────┴────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘

  B5. nlsq/shear_weighting.py

  Status: REMOVED
  Sinc² angular sensitivity weights are homodyne-specific. Heterodyne velocity phase sensitivity is uniform in φ (cos is not peaked like sinc²). Already correctly identified and removed per memory note.

  B6. nlsq/hierarchical.py

  Status: DONE (736 → 355 lines)

  ┌──────────────────────────────────────┬───────────────────────────────────────┬────────────────────┬─────────────────────────────────────────────────────────────────────────────────────────────────────┐
  │               Homodyne               │              Heterodyne               │       Delta        │                                            Justification                                            │
  ├──────────────────────────────────────┼───────────────────────────────────────┼────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────┤
  │ Stage 1: fit physics₇; Stage 2: fit  │ Stage 1: fit physics₁₄; Stage 2: fit  │ More params in     │ Same algorithm, just 14 free physics params instead of 7. May need more iterations in stage 1 due   │
  │ scaling                              │ scaling                               │ stage 1            │ to larger search space.                                                                             │
  └──────────────────────────────────────┴───────────────────────────────────────┴────────────────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────┘

  B7. nlsq/wrapper.py

  Status: REMOVED (integrated into adapter.py)
  Heterodyne merged NLSQWrapper functionality into NLSQAdapter with fallback to scipy.optimize.least_squares internally.

  B8. All other NLSQ files

  Status: DONE (model-agnostic; minimal changes)
  - fallback_chain.py — Strategy selection unchanged
  - recovery.py — 3-attempt retry unchanged
  - cmaes_wrapper.py — Takes any objective function
  - multistart.py — LHS sampling in any bounds
  - adaptive_regularization.py — CV-based λ unchanged
  - gradient_monitor.py — Gradient norms unchanged
  - strategies/ — All take residual function closures
  - validation/ — Threshold checks; param names updated

  ---
  C. CMC OPTIMIZATION ADAPTATIONS

  C1. cmc/core.py — CMC Entry

  Status: DONE (1568 → 1188 lines)

  ┌─────────────────────────────────────────────────────────────────┬─────────────────────────────────────────────────────┬───────────────────────────────┬───────────────────────────────────────────────────┐
  │                            Homodyne                             │                     Heterodyne                      │             Delta             │                   Justification                   │
  ├─────────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────┼───────────────────────────────┼───────────────────────────────────────────────────┤
  │ fit_mcmc_jax(data, config, parameter_space, analysis_mode, ...) │ fit_cmc_jax(model, c2_data, phi_angle, config, ...) │ Interface mirrors NLSQ change │ Takes HeterodyneModel; no analysis_mode dispatch. │
  ├─────────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────┼───────────────────────────────┼───────────────────────────────────────────────────┤
  │ Consensus MC combination                                        │ Same                                                │ Identical                     │ Model-agnostic posterior combination.             │
  └─────────────────────────────────────────────────────────────────┴─────────────────────────────────────────────────────┴───────────────────────────────┴───────────────────────────────────────────────────┘

  C2. cmc/model.py — NumPyro Model

  Status: DONE (1168 → 953 lines; completely rewritten internals)

  ┌─────────────────────────────────────────────────┬─────────────────────────────────────────────────────┬─────────────────────┬──────────────────────────────────────────────────────────────────────────┐
  │                    Homodyne                     │                     Heterodyne                      │        Delta        │                              Justification                               │
  ├─────────────────────────────────────────────────┼─────────────────────────────────────────────────────┼─────────────────────┼──────────────────────────────────────────────────────────────────────────┤
  │ get_xpcs_model() returns model sampling 7       │ get_heterodyne_model() returns model sampling up to │ Different prior set │ Heterodyne samples D₀_ref, α_ref, D_off_ref, D₀_sam, α_sam, D_off_sam,   │
  │ physics params                                  │  14 physics params                                  │                     │ v₀, β, v_off, f₀, f₁, f₂, f₃, φ₀.                                        │
  ├─────────────────────────────────────────────────┼─────────────────────────────────────────────────────┼─────────────────────┼──────────────────────────────────────────────────────────────────────────┤
  │ Model calls compute_g1_total_with_precomputed() │ Model calls compute_c2_elementwise() or             │ Different physics   │ Heterodyne can't use g₁ intermediate; must compute c₂ directly.          │
  │                                                 │ compute_c2_heterodyne()                             │ dispatch            │                                                                          │
  ├─────────────────────────────────────────────────┼─────────────────────────────────────────────────────┼─────────────────────┼──────────────────────────────────────────────────────────────────────────┤
  │ Likelihood: Normal(offset + contrast × g₁²,     │ Likelihood: Normal(c₂_model, sigma)                 │ c₂ computed inside  │ Heterodyne c₂ already includes contrast/offset via                       │
  │ noise)                                          │                                                     │ model               │ compute_c2_heterodyne.                                                   │
  └─────────────────────────────────────────────────┴─────────────────────────────────────────────────────┴─────────────────────┴──────────────────────────────────────────────────────────────────────────┘

  C3. cmc/priors.py — Prior Construction

  Status: DONE (1106 → 920 lines)

  ┌──────────────────────────────┬───────────────────────────────────────────────────────────────┬────────────────────────────┬─────────────────────────────────────────────────────────────────────────────┐
  │           Homodyne           │                          Heterodyne                           │           Delta            │                                Justification                                │
  ├──────────────────────────────┼───────────────────────────────────────────────────────────────┼────────────────────────────┼─────────────────────────────────────────────────────────────────────────────┤
  │ Priors for: D₀, α, D_off,    │ Priors for: D₀_ref, α_ref, D_off_ref, D₀_sam, α_sam,          │ 14 prior distributions     │ Registry-driven; each param gets TruncatedNormal from heterodyne's          │
  │ γ̇₀, β, γ̇_off, φ₀             │ D_off_sam, v₀, β, v_off, f₀, f₁, f₂, f₃, φ₀                   │                            │ parameter_registry.                                                         │
  ├──────────────────────────────┼───────────────────────────────────────────────────────────────┼────────────────────────────┼─────────────────────────────────────────────────────────────────────────────┤
  │ Log-space for D₀, γ̇₀         │ Log-space for D₀_ref, D₀_sam, v₀                              │ Three log-space params     │ Velocity v₀ spans similar dynamic range as γ̇₀.                              │
  │                              │                                                               │ instead of two             │                                                                             │
  ├──────────────────────────────┼───────────────────────────────────────────────────────────────┼────────────────────────────┼─────────────────────────────────────────────────────────────────────────────┤
  │ No fraction priors           │ Fraction priors: f₀∈[0,1], f₁∈[-10,10], f₂∈[-1e4,1e4],        │ 4 new priors               │ Fraction params are new to heterodyne; f₀ and f₃ use Beta-like priors       │
  │                              │ f₃∈[0,1]                                                      │                            │ (bounded [0,1]); f₁ and f₂ use TruncatedNormal.                             │
  └──────────────────────────────┴───────────────────────────────────────────────────────────────┴────────────────────────────┴─────────────────────────────────────────────────────────────────────────────┘

  C4. cmc/reparameterization.py — Decorrelation Transforms

  Status: DONE (336 → 297 lines)

  ┌─────────────────────────────────────────────┬────────────────────────────────────────────┬──────────────────────────┬───────────────────────────────────────────────────────────────────────────────────┐
  │                  Homodyne                   │                 Heterodyne                 │          Delta           │                                   Justification                                   │
  ├─────────────────────────────────────────────┼────────────────────────────────────────────┼──────────────────────────┼───────────────────────────────────────────────────────────────────────────────────┤
  │ D₀↔α decorrelation: D_ref = D₀ × t_ref^α    │ D₀_ref↔α_ref AND D₀_sam↔α_sam              │ Two pairs instead of one │ Two independent transport components each need decorrelation. t_ref is shared     │
  │                                             │                                            │                          │ (same time grid).                                                                 │
  ├─────────────────────────────────────────────┼────────────────────────────────────────────┼──────────────────────────┼───────────────────────────────────────────────────────────────────────────────────┤
  │ γ̇₀↔β decorrelation: log_γ_ref = log(γ̇₀ ×    │ v₀↔β decorrelation: log_v_ref = log(v₀ ×   │ Velocity replaces shear  │ Same mathematical structure: prefactor×t^exponent → log-reference                 │
  │ t_ref^β)                                    │ t_ref^β)                                   │ rate                     │ reparameterization.                                                               │
  ├─────────────────────────────────────────────┼────────────────────────────────────────────┼──────────────────────────┼───────────────────────────────────────────────────────────────────────────────────┤
  │ compute_t_ref(dt, t_max)                    │ Same                                       │ Identical                │ Geometric mean is model-agnostic.                                                 │
  └─────────────────────────────────────────────┴────────────────────────────────────────────┴──────────────────────────┴───────────────────────────────────────────────────────────────────────────────────┘

  C5. cmc/scaling.py — Bounded Transforms

  Status: DONE (344 → 254 lines)
  Model-agnostic tanh-based bounded transforms. No physics assumptions. Minimal changes.

  C6. cmc/diagnostics.py — Convergence

  Status: DONE (1272 → 1188 lines)
  Model-agnostic R-hat, ESS, BFMI, bimodality checks. Parameter names updated.

  C7. cmc/backends/

  Status: DONE (renamed + cpu/gpu backends added)
  - multiprocessing.py → multiprocessing_backend.py
  - pjit.py → pjit_backend.py
  - New: cpu_backend.py, gpu_backend.py
  All model-agnostic.

  ---
  D. CONFIG & DATA ADAPTATIONS

  D1. config/parameter_registry.py

  Status: DONE

  ┌──────────────────────┬────────────────────────────────────────────────────┐
  │ Homodyne (9 entries) │              Heterodyne (16 entries)               │
  ├──────────────────────┼────────────────────────────────────────────────────┤
  │ contrast, offset     │ contrast, offset (same)                            │
  ├──────────────────────┼────────────────────────────────────────────────────┤
  │ D₀, α, D_offset      │ D₀_ref, α_ref, D_off_ref, D₀_sam, α_sam, D_off_sam │
  ├──────────────────────┼────────────────────────────────────────────────────┤
  │ γ̇₀, β, γ̇_offset, φ₀  │ v₀, β, v_offset, f₀, f₁, f₂, f₃, φ₀                │
  └──────────────────────┴────────────────────────────────────────────────────┘

  All bounds, defaults, and prior specs rewritten for heterodyne physics.

  D2. config/parameter_space.py

  Status: DONE
  Prior specs updated for 14+2 parameter set. Single-angle stabilization logic retained (model-agnostic for contrast/offset).

  D3. config/physics_validators.py

  Status: DONE
  Constraint rules rewritten for heterodyne params: D₀_ref>0, D₀_sam>0, v₀≥0 (or allow negative?), f₀∈[0,1], f₃∈[0,1], etc.

  ---
  E. ALGORITHMS NOT PORTED (Correctly Absent)

  ┌───────────────────────────────────────────────────┬───────────────────────────────────────────────────────────────────────────────────────┐
  │                Homodyne Algorithm                 │                                   Reason Not Ported                                   │
  ├───────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────────────┤
  │ shear_weighting.py                                │ sinc²-specific angular sensitivity; heterodyne velocity cos has uniform φ sensitivity │
  ├───────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────────────┤
  │ ShearModel (standalone)                           │ No physical meaning in heterodyne; shear is replaced by directed velocity             │
  ├───────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────────────┤
  │ Analysis mode "laminar_flow" vs "static" dispatch │ Heterodyne uses "static_ref", "static_both", "two_component" modes instead            │
  ├───────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────────────┤
  │ sinc_prefactor computation                        │ No sinc term in heterodyne                                                            │
  ├───────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────────────┤
  │ stator_rotor_gap L parameter                      │ Not a physical parameter in heterodyne geometry                                       │
  └───────────────────────────────────────────────────┴───────────────────────────────────────────────────────────────────────────────────────┘

  ---
  F. KEY DIVERGENCES WITH JUSTIFICATION

  ┌────────────────────────┬───────────────────────────────────────┬─────────────────────────────────────────────────┬──────────────────────────────────────────────────────────────────────────────────────┐
  │      Line/Pattern      │               Homodyne                │                   Heterodyne                    │                                         Why                                          │
  ├────────────────────────┼───────────────────────────────────────┼─────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────┤
  │ Transport rate floor   │ D(t) ≥ 0 (floored)                    │ J(t) ≥ 0 (floored)                              │ Both floor transport coefficients; negative diffusion is unphysical                  │
  ├────────────────────────┼───────────────────────────────────────┼─────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────┤
  │ Velocity rate floor    │ γ̇(t) ≥ 0 (floored)                    │ v(t) not floored                                │ Velocity enters cos(phase); negative velocity = reversed flow direction (physically  │
  │                        │                                       │                                                 │ meaningful)                                                                          │
  ├────────────────────────┼───────────────────────────────────────┼─────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────┤
  │ g₁ intermediate        │ Computed and squared: c₂ = contrast × │ Not computed; c₂ directly from 3-term sum       │ Heterodyne correlation is not expressible as a single g₁²                            │
  │                        │  g₁²                                  │                                                 │                                                                                      │
  ├────────────────────────┼───────────────────────────────────────┼─────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────┤
  │ Fraction arrays        │ Not present                           │ f_s(t₁), f_r(t₁), products                      │ Two-beam mixing ratio varies in time; new physics                                    │
  ├────────────────────────┼───────────────────────────────────────┼─────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────┤
  │ Cross-term             │ None                                  │ 2×f_cross×half_tr_ref×half_tr_sample×cos(phase) │ Interference between reference and sample beams; absent in homodyne                  │
  ├────────────────────────┼───────────────────────────────────────┼─────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────┤
  │ Normalization          │ None (g₁²∈[0,1])                      │ f² = (f_s²+f_r²)₁×(f_s²+f_r²)₂                  │ Fraction weighting requires explicit normalization                                   │
  ├────────────────────────┼───────────────────────────────────────┼─────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────┤
  │ contrast bounds        │ [0, 1]                                │ [0, 10]                                         │ Heterodyne can amplify via cross-term constructive interference                      │
  ├────────────────────────┼───────────────────────────────────────┼─────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────┤
  │ offset bounds          │ [0.5, 1.5]                            │ [-1, 1]                                         │ Heterodyne cross-term can produce negative baseline shift                            │
  ├────────────────────────┼───────────────────────────────────────┼─────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────┤
  │ trapezoid_cumsum       │ dt external                           │ dt parameter                                    │ Convenience; avoids repeated dt multiplication at many call sites                    │
  ├────────────────────────┼───────────────────────────────────────┼─────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────┤
  │ Signed velocity        │ Not needed (sinc is even)             │ Required for cos(phase)                         │ cos(phase) is odd in the integral sign; must preserve sign                           │
  │ integral               │                                       │                                                 │                                                                                      │
  ├────────────────────────┼───────────────────────────────────────┼─────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────┤
  │ Log-space params       │ D₀, γ̇₀                                │ D₀_ref, D₀_sam, v₀                              │ Three parameters span wide dynamic range (three log-space vs two)                    │
  └────────────────────────┴───────────────────────────────────────┴─────────────────────────────────────────────────┴──────────────────────────────────────────────────────────────────────────────────────┘

  ---
  ★ Insight ─────────────────────────────────────
  Why "identical code is a bug": The fundamental difference is that homodyne XPCS measures intensity-intensity correlations g₂ = 1 + |g₁|², which factors cleanly into a single field correlation g₁. Heterodyne
  XPCS mixes a reference beam with the sample, producing c₂ = (ref + sample + cross)/f² — an additive three-term structure that cannot be factored into a single g₁². Any code that assumes multiplicative
  g₁_diff × g₁_shear → square → scale is encoding the wrong physics for heterodyne.

  The velocity ≠ shear distinction matters numerically: Homodyne shear enters as sinc²(∫γ̇ dt), which is bounded [0,1] and oscillatory with zeros — it needs careful numerical treatment (safe_sinc, non-negative
  floor). Heterodyne velocity enters as cos(q·cos(φ)·∫v dt), which is bounded [-1,1] and smooth — it needs signed integrals and no floor, because negative velocity is physical (reversed flow).

  Fraction normalization is the key new complexity: The f² denominator creates a new class of numerical issues (division by near-zero when f_s ≈ 0 or f_s ≈ 1) that homodyne never encounters. All jnp.where(f² >
   1e-10, ...) guards in heterodyne are new safety that has no homodyne counterpart.
  ─────────────────────────────────────────────────

  Summary

  Of ~85 distinct algorithms inventoried across homodyne:
  - ~30 are model-specific (encode homodyne g₁²/sinc² assumptions) — all have been rewritten for heterodyne's 3-term/cos/fraction model
  - ~55 are model-agnostic (optimization infrastructure) — ported with parameter-count and name updates
  - 1 algorithm removed (shear_weighting) — correctly identified as inapplicable
  - 0 algorithms missing — heterodyne has full parity with homodyne's algorithm set

  The heterodyne codebase is a complete, correctly adapted port. No homodyne algorithm was blindly copied.
